package com.superhero.common.pojo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.Map;


@ApiModel(description = "响应结果")
@Data
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiResult<T> implements Serializable {
 
    public static final String RESULT_CODE = "resultCode";
    public static final String DATA = "data";
    public static final String ERROR_MSG = "errorMsg";

    /**
     * 操作成功
     */
    public final static String MSG_SUCCESS = "SUCCESS";

    /**
     * 服务异常
     */
    public final static String MSG_ERROR_SYS = "[服务异常]";

    public final static String MSG_ERROR_PARAM = "[请求参数缺失]请携带以下请求参数: ";


    public static final int DEFAULT_SUCCESS_CODE = 0;

    /**
     * 服务异常
     */
    public final static Integer CODE_ERROR_SYS = 999999;

    /**
     * 请求参数缺失
     */
    public final static Integer CODE_ERROR_PARAM = 999998;


    //================properties================//

    @ApiModelProperty(required = true, value = "返回码,非0表示错误")
    private Integer resultCode = 0;

    @ApiModelProperty(value = "错误的描述信息")
    private String errorMsg = "";

    @ApiModelProperty(value = "返回的数据内容")
    private T data;

    //================constructor method================//

    public ApiResult() {
    }

    public ApiResult(Integer resultCode, String errorMsg) {
        this.resultCode = resultCode;
        this.errorMsg = errorMsg;
    }

    public ApiResult(Integer resultCode, String errorMsg, T data) {
        this.resultCode = resultCode;
        this.errorMsg = errorMsg;
        this.data = data;
    }

    //================static constructor method================//

    /**
     * 构造一个正常响应
     *
     * @return
     */
    public static <T> ApiResult<T> success() {
        return success(null);
    }

    /**
     * 构造一个正常响应
     *
     * @param data
     * @return
     */
    public static <T> ApiResult<T> success(T data) {
        ApiResult<T> result = new ApiResult<>();
        result.setData(data);
        return result;
    }

    /**
     * 操作失败，返回默认的错误信息
     *
     * @return
     */
    public static <T> ApiResult<T> error() {
        return error(CODE_ERROR_SYS, MSG_ERROR_SYS);
    }


    /**
     * 操作失败，返回默认的错误码，指定错误信息
     *
     * @return
     */
    public static <T> ApiResult<T> error(String msg) {
        return error(CODE_ERROR_SYS, msg);
    }

    /**
     * 构造一个错误响应
     *
     * @param code
     * @param msg
     * @return
     */
    public static <T> ApiResult<T> error(Integer code, String msg) {
        ApiResult<T> result = new ApiResult<>();
        result.setResultCode(code);
        result.setErrorMsg(msg);
        return result;
    }

    /**
     * 判断是否操作成功
     *
     * @return
     */
    @ApiModelProperty(hidden = true)
    @JSONField(serialize = false, deserialize = false)
    @JsonIgnore
    public boolean isSuccess() {
        return null != this.getResultCode() && 0 == this.getResultCode();
    }

    /**
     * 获取业务数据，转化为map对象
     *
     * @return
     */
    @ApiModelProperty(hidden = true)
    @JSONField(serialize = false, deserialize = false)
    @JsonIgnore
    public <K, V> Map<K, V> getMapData() {
        Map<K, V> map;
        Object object = getData();
        if (null == object) {
            return null;
        }

        JSON json = (JSON) JSONObject.toJSON(object);

        map = json.toJavaObject(Map.class);
        return map;
    }

    /**
     * 返回给前端的json
     *
     * @return
     */
    public JSONObject toJSON() {
        Class dataClass = null;
        JSONObject json = new JSONObject();
        json.put(RESULT_CODE, resultCode);
        json.put(ERROR_MSG, errorMsg);
        if (data != null) {
            json.put(DATA, data);
            dataClass = data.getClass();
        }
        return json;
    }

}
